module.exports = app => {

    const assert = require('http-assert')
    const User = require('../../models/system/User')
    const Department = require('../../models/system/Department')
    const Role = require('../../models/system/Role')
    const auth = require('../../middleWares/auth')
    const {handleTree} = require('../../utils/tools')

    /**
     * @description 查询信息列表
     * @param pageNum {Number} 页码
     * @param pageSize {Number} 数量
     * */
    app.get('/user', auth('system:user:list'), async (req, res) => {
        const {pageNum, pageSize, deptCode, keywords, status} = req.query
        const regexp = new RegExp(keywords, 'i')
        const filter = {
            $or: [{name: {$regex: regexp}}]
        }
        if (status) filter.status = status
        if (deptCode) {
            const deptList = await Department.find()
            const tree = await handleTree(deptList, 'deptCode', 'parentCode')
            const data = await getDepartmentById(tree, deptCode)
            const codeList = await returnCode(data)
            filter.dept = {$in: codeList}
        }
        const total = await User
            .find(filter)
            .countDocuments()
        const rows = await User
            .find(filter)
            .populate('dept')
            .skip((pageNum - 1) * parseInt(pageSize))
            .limit(parseInt(pageSize))

        res.send({
            code: 200,
            message: '操作成功',
            total,
            rows
        })
    })

    /**
     * @description 返回基本信息列表
     * @param pageNum {Number} 页码
     * @param pageSize {Number} 数量
     * */
    app.get('/user/basic', auth('system:user:list'), async (req, res) => {
        const {pageNum, pageSize, grade} = req.query
        const filter = grade ? {grade} : null
        const total = await User
            .find(filter)
            .countDocuments()
        const rows = await User
            .find(filter, {name: 1, userName: 1, grade: 1})
            .populate('score')
            .skip((pageNum - 1) * parseInt(pageSize))
            .limit(parseInt(pageSize))

        res.send({
            code: 200,
            message: '操作成功',
            total,
            rows
        })
    })

    /**
     * @description 根据主键id查询详情信息
     * */
    app.get('/user/:id', auth('system:user:detail'), async (req, res) => {
        const data = await User.findById(req.params.id)

        res.send({
            code: 200,
            message: '操作成功',
            data
        })
    })

    /**
     * @description 根据token查询详情消息
     * */
    app.get('/getInfo', auth('*:*:*'), async (req, res) => {
        let roles = await Role
            .find({_id: {$in: req.user.roles}})
            .distinct('roleType')

        res.send({
            code: 200,
            message: '操作成功',
            data: req.user,
            permissions: req.user.permissions.filter(v => Boolean(v)),
            roles
        })
    })

    /**
     * @description 查询用户个人资料
     * */
    app.get('/profile', auth('*:*:*'), async(req, res) => {
        res.send({
            code: 200,
            message: '操作成功',
            data: req.user
        })
    })

    /**
     * @description 根据主键id修改用户个人资料
     * @param req.body {Object} 数据
     * */
     app.put('/profile', auth('*:*:*'), async (req, res) => {
        await User.findByIdAndUpdate(req.body._id, req.body)

        res.send({
            code: 200,
            message: '操作成功'
        })
    })

    /**
     * @description 修改个人密码
     * */
     app.put('/profile/updatePwd', auth('*:*:*'), async (req, res) => {
        const {oldPassword, newPassword} = req.body
        const user = await User.findById(req.user._id).select('password')
        const valid = require('bcrypt').compareSync(oldPassword, user.password)
        assert(valid, 422, '旧密码不正确，请重新输入旧密码。')
        await User.findByIdAndUpdate(req.user._id, {password: newPassword})

        res.send({
            code: 200,
            message: '操作成功'
        })
    })

    /**
     * @description 添加信息
     * @param req.body {Object} 数据
     * */
    app.post('/user', auth('system:user:insert'), async (req, res) => {
        const {userName} = req.body
        const user = await User.findOne({userName})
        assert(!user, 500, '该用户信息已经存在，请不要重复添加。')
        await User.create(req.body)

        res.send({
            code: 200,
            message: '操作成功'
        })
    })

    /**
     * @description 批量删除
     * @param req.body {Array} 信息的主键id的集合
     * */
    app.delete('/user', auth('system:user:delete'), async (req, res) => {
        await User.deleteMany({_id: {$in: req.body}})

        res.send({
            code: 200,
            message: '操作成功'
        })
    })

    /**
     * @description 根据主键id修改信息
     * @param req.body {Object} 数据
     * */
    app.put('/user', auth('system:user:update'), async (req, res) => {
        await User.findByIdAndUpdate(req.body._id, req.body)

        res.send({
            code: 200,
            message: '操作成功'
        })
    })

    /**
     * @description 根据userName修改信息
     * @param userName {String} 编号
     * */
    app.put('/user/:userName', auth('system:user:update'), async (req, res) => {
        await User.findOneAndUpdate({userName: req.params.userName}, req.body)

        res.send({
            code: 200,
            message: '操作成功'
        })
    })

    /**
     * @description 重置密码
     * */
    app.put('/user/reset/:id', auth('system:user:update'), async (req, res) => {
        await User.findByIdAndUpdate(req.params.id, req.body)

        res.send({
            code: 200,
            message: '操作成功'
        })
    })

}

// 查找树结构里的某个节点
async function getDepartmentById(list, id) {
    //判断list是否是数组
    if (!list instanceof Array) {
        return null
    }
    //遍历数组
    for (let i in list) {
        let item = list[i]
        if (item.deptCode === id) {
            return item
        } else {
            //查不到继续遍历
            if (item.children && item.children.length) {
                let value = await getDepartmentById(item.children, id)
                //查询到直接返回
                if (value) {
                    return value
                }
            }
        }
    }
}

// 返回树结构里的code集合
async function returnCode(data) {
    let arr = []
    queryNode(data)
    function queryNode(data) {
        if (data._id) {
            arr.push(data._id)
        }
        if (data.children && data.children.length) {
            for (let i in data.children) {
                const item = data.children[i]
                queryNode(item)
            }
        }
    }
    return arr
}